package per.zqx.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Service;
import per.zqx.dto.Order;
import per.zqx.mapper.DispatcherMapper;
import per.zqx.pojo.Dispatcher;

import java.io.IOException;
import java.time.LocalDateTime;

/**
 * DispatcherServiceImpl,
 *
 * @author Sa, Zhang 2021-08-15 16:41
 */
@Service
public class DispatcherCustomer {

    @Autowired
    DispatcherMapper dispatcherMapper;

    /**
     *
     * @param orderMsg 消息本身
     * @param channel com.rabbitmq.client下的Channel
     * @param tag 消息标签
     * @throws IOException
     */
    @RabbitListener(queues = "acid.order.queue")
    public void receiveMsg(String orderMsg, Channel channel,@Header(AmqpHeaders.DELIVERY_TAG) Long tag) throws IOException {
        System.out.println("派单系统收到订单 ====> " + orderMsg);
        try {
            JSONObject o = (JSONObject) JSONObject.parse(orderMsg);
            Order order = JSON.toJavaObject(o, Order.class);
            System.out.println(1/0);
            // 本地事务问题吗，try-catch里，存数据库在异常之前，事务不会回滚
            // 一定要考虑幂等性问题
                // 利用数据库，主键或者唯一键
                // 分布式锁解决幂等性问题
            saveDispatcher(order);
            channel.basicAck(tag,false);
        }catch (Exception e){
            /**
             * 消息Tag，是否多条处理，requeue重发；
             * 选择不重发，直接打入死信队列，
             * 配置的重发自动失效。重发与try-catch互斥
             * 如果要使用尝试（requeue设置true)，不要加try-catch，否则一直会死循环
             */
            channel.basicNack(tag,false,false);
        }
    }

    public void saveDispatcher(Order order) {
        LocalDateTime now = LocalDateTime.now();
        Dispatcher dispatcher = new Dispatcher();
        dispatcher.setOrderId(order.getId());
        dispatcher.setBuyer(order.getBuyer());
        dispatcher.setCreateTime(now);
        dispatcher.setUpdateTime(now);
        dispatcherMapper.save(dispatcher);
    }
}
